package cs275.ants.graph.antgraph;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Set;

import cs275.ants.agent.Ant;
import cs275.ants.graph.antgraph.AntGraph;
import cs275.ants.graph.antgraph.AntGraphVertex;
import cs275.ants.graph.antgraph.AntGraphEdge;
import cs275.ants.graph.base.GraphEdge;
import cs275.ants.graph.base.GraphVertex;
import junit.framework.TestCase;

public class AntGraphTest extends TestCase {
	// serialization test 
	public void testIsSerializable() throws Exception {
		
		// create a graph
		AntGraph tGraph = new AntGraph(); 
		AntGraphVertex vertex1 = new AntGraphVertex(new ArrayList<Ant>(), 0, 0); // 1 ant 
		vertex1.addAnt(new Ant(tGraph, vertex1));
		
		AntGraphVertex vertex2 = new AntGraphVertex(new ArrayList<Ant>(), 0, 1); // 2 ants
		vertex2.addAnt(new Ant(tGraph, vertex2));
		vertex2.addAnt(new Ant(tGraph, vertex2));

		AntGraphVertex vertex3 = new AntGraphVertex(new ArrayList<Ant>(), 0, 2); // 3 ants	
		vertex3.addAnt(new Ant(tGraph, vertex3));
		vertex3.addAnt(new Ant(tGraph, vertex3));
		vertex3.addAnt(new Ant(tGraph, vertex3));
		
		tGraph.addVertex(vertex1);
		tGraph.addVertex(vertex2);
		tGraph.addVertex(vertex3);
		AntGraphEdge newEdge = new AntGraphEdge(vertex2, vertex3);
		tGraph.addEdge(newEdge);
		
	    ByteArrayOutputStream out = new ByteArrayOutputStream();
	    ObjectOutputStream oos = new ObjectOutputStream(out);
	    oos.writeObject(tGraph);
	    oos.close();
	    assertTrue(out.toByteArray().length > 0);

	}
	
	public void testRoundTripSerialization() throws Exception {

		// create a graph
		AntGraph tGraph = new AntGraph(); 
		AntGraphVertex vertex1 = new AntGraphVertex(new ArrayList<Ant>(), 0, 0); // 1 ant 
		vertex1.addAnt(new Ant(tGraph, vertex1));
		
		AntGraphVertex vertex2 = new AntGraphVertex(new ArrayList<Ant>(), 0, 1); // 2 ants
		vertex2.addAnt(new Ant(tGraph, vertex2));
		vertex2.addAnt(new Ant(tGraph, vertex2));

		AntGraphVertex vertex3 = new AntGraphVertex(new ArrayList<Ant>(), 0, 2); // 3 ants	
		vertex3.addAnt(new Ant(tGraph, vertex3));
		vertex3.addAnt(new Ant(tGraph, vertex3));
		vertex3.addAnt(new Ant(tGraph, vertex3));
		
		tGraph.addVertex(vertex1);
		tGraph.addVertex(vertex2);
		tGraph.addVertex(vertex3);
		AntGraphEdge newEdge = new AntGraphEdge(vertex2, vertex3);
		tGraph.addEdge(newEdge);

	    // serialize
	    ByteArrayOutputStream out = new ByteArrayOutputStream();
	    ObjectOutputStream oos = new ObjectOutputStream(out);
	    oos.writeObject(tGraph);
	    oos.close();

	    // deserialize
	    byte[] pickled = out.toByteArray();
	    ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(pickled));
	    Object o = ois.readObject();
	    AntGraph copy = (AntGraph) o;

	    // test the result (see if there are vertices with 1 ant, 2 ant, 3 ants), 
	    // and the 2 ants and 3 ants are connected with 23 as weight
	    AntGraphVertex v1 = null;
	    AntGraphVertex v2 = null; 
	    AntGraphVertex v3 = null; 
	    
	    Set<GraphVertex> vertices = copy.getAllVertices(); 
	    Iterator<GraphVertex> iterator = vertices.iterator();
	    while (iterator.hasNext()) { 
	    	AntGraphVertex v = (AntGraphVertex)iterator.next(); 
	    	List<Ant> l = v.getAnts();
	    	int numAnts = l.size();
	    	assertTrue((numAnts == 1 || numAnts == 2 || numAnts == 3));
	    	switch (numAnts) {  
	    		case 1: 
	    			v1 = v; 
	    			break;
	    		case 2:
	    			v2 = v;
	    			break;
	    		case 3:
	    			v3 = v; 
	    			break;	    			
	    	}	    	
	    }
	    
	    assertTrue(copy.getEdgesByVertex(v1).isEmpty());
	    assertFalse(copy.getEdgesByVertex(v2).isEmpty());
	    assertFalse(copy.getEdgesByVertex(v3).isEmpty());
	    HashSet<GraphEdge> e2 = copy.getEdgesByVertex(v2);
	    HashSet<GraphEdge> e3 = copy.getEdgesByVertex(v3);
	    assertEquals(e2.size(), 1);
	    assertEquals(e3.size(), 1);
	    
	    Iterator<GraphEdge> it = e2.iterator();
	    GraphEdge edge2 = it.next(); 
	    it = e3.iterator();
	    GraphEdge edge3 = it.next(); 
	    assertTrue(edge2 instanceof AntGraphEdge); 
	    assertTrue(edge3 instanceof AntGraphEdge);	    
	    assertEquals(edge2, edge3); 
	    
//	    assertEquals(tGraph, copy);	    
	  }	

}
